package com.gitee.yongzhuzl.commonutil.util.result;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.List;

/**
 * description: 自定义响应结果
 * @author 朱正磊
 * @date 2018年5月23日 上午11:12:51
 */
public class ResponseResult<T> implements Serializable {

    private static final Logger log = LoggerFactory.getLogger(ResponseResult.class);

	private static final long serialVersionUID = 7942045819282428627L;

	/**
	 * 定义jackson对象
	 */
	private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 状态码常量
     */
    public static final int SUCCESS_CODE = 200;
    public static final int ERROR_CODE = 500;

	/**
	 * 业务状态
	 */
    @JsonProperty(index = 1)
	private final Integer code;

	/**
	 * 响应消息
	 */
    @JsonProperty(index = 2)
	private final String msg;

	/**
	 * 业务数据
	 */
    @JsonProperty(index = 3)
	private final T data;

    /**
     * 私有构造函数，通过静态方法构建实例
     */
	private ResponseResult(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

	/**
	 * description: 构造函数设置响应业务状态
	 * @param code 业务状态
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildResult(Integer code) {
		return new ResponseResult<>(code, null, null);
	}

	/**
	 * description: 构造函数只设置响应消息
	 * @param msg 响应消息
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildResult(String msg) {
		return new ResponseResult<>(null, msg, null);
	}

	/**
	 * description: 构造函数同时设置响应业务状态和响应消息
	 * @param code 业务状态
	 * @param msg 响应消息
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildResult(Integer code, String msg) {
		return new ResponseResult<>(code, msg, null);
	}

	/**
	 * description: 构造函数同时设置响应业务状态、响应消息、响应数据
	 * @param code 业务状态
	 * @param msg 响应消息
	 * @param data 业务数据
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildResult(Integer code, String msg, T data) {
		return new ResponseResult<>(code, msg, data);
	}

	/**
	 * description: 调用服务成功
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildSuccess() {
		return new ResponseResult<>(SUCCESS_CODE, "success", null);
	}

	/**
	 * description: 调用服务成功
	 * @param data 业务数据
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildSuccess(T data) {
		return new ResponseResult<>(SUCCESS_CODE, "success", data);
	}

	/**
	 * description: 调用服务成功
	 * @param msg 响应消息
	 * @param data 业务数据
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildSuccess(String msg, T data) {
		return new ResponseResult<>(SUCCESS_CODE, msg, data);
	}

	/**
	 * description: 调用服务失败
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildError() {
		return new ResponseResult<>(ERROR_CODE, "error", null);
	}

	/**
	 * description: 调用服务失败
	 * @param msg 响应消息
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> buildError(String msg) {
		return new ResponseResult<>(ERROR_CODE, msg, null);
	}

	/**
	 * 说明：data为null
	 * description: json字符串转ResponseResult对象
	 * @param json json字符串
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> format(String json) {
		try {
			// json字符串中data为null，将json字符串转换成ResponseResult对象
			return MAPPER.readValue(json, new TypeReference<ResponseResult<T>>(){});
		} catch (Exception e) {
            log.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 说明：data为T类型的单个对象
	 * description: json字符串转ResponseResult对象
	 * @param json json字符串
	 * @param clazz T类型
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> formatToPojo(String json, Class<T> clazz) {
		try {
			if (clazz == null) {
				// 如果json字符串中data为null，将json字符串转换成ResponseResult对象
				return MAPPER.readValue(json, new TypeReference<ResponseResult<T>>(){});
			}
			JsonNode jsonNode = MAPPER.readTree(json);
			// 获取data的值
			JsonNode data = jsonNode.get("data");
			// obj用来存储data
			T obj = null;
			if (!data.isNull()) {
				// 如果data不为null
				obj = MAPPER.readValue(data.traverse(), clazz);
			}
			// 将json字符串转换成ResponseResult对象
			return buildResult(jsonNode.get("code").intValue(), jsonNode.get("msg").asText(), obj);
		} catch (Exception e) {
            log.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 说明：data为T类型对象的集合
	 * description: json字符串转ResponseResult对象
	 * @param json json字符串
	 * @param clazz T类型
	 * @return 返回自定义响应对象
	 */
	public static<T> ResponseResult<T> formatToList(String json, Class<T> clazz) {
		try {
			if (clazz == null) {
				// 如果json字符串中data为null，将json字符串转换成ResponseResult对象
				return MAPPER.readValue(json, new TypeReference<ResponseResult<T>>(){});
			}
			JsonNode jsonNode = MAPPER.readTree(json);
			// 获取data的值
			JsonNode data = jsonNode.get("data");
			// obj用来存储data
			T obj = null;
			if (data.isArray() && !data.isEmpty()) {
				// 如果data是数组格式并且长度不为0
				obj = MAPPER.readValue(data.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
			}
			// 将json字符串转换成ResponseResult对象
			return buildResult(jsonNode.get("code").intValue(), jsonNode.get("msg").asText(), obj);
		} catch (Exception e) {
            log.error(e.getMessage(), e);
		}
		return null;
	}

	public Integer getCode() {
		return code;
	}

	public String getMsg() {
		return msg;
	}

	public T getData() {
		return data;
	}

    @Override
    public String toString() {
        return "ResponseResult{" +
                "code=" + code +
                ", msg='" + msg + '\'' +
                ", data=" + data +
                '}';
    }

}
